package com.webchat.common.config.interceptor;


import com.webchat.common.config.annotation.BehaviorLimiter;
import com.webchat.common.constants.WebConstant;
import com.webchat.common.exception.BusinessException;
import com.webchat.common.helper.SessionHelper;
import com.webchat.common.service.RedisService;
import com.webchat.common.util.JsonUtil;
import com.webchat.common.util.http.HttpHelper;
import com.webchat.domain.vo.request.ResourceBehaviorRequestVO;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import java.io.IOException;
import java.lang.reflect.Method;

@Component
public class BehaviorLimiterInterceptor implements HandlerInterceptor {

    @Autowired
    private RedisService redisService;

    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response,
                             Object handler) {
        // 检查 handler 是否为 HandlerMethod 类型
        if (!(handler instanceof HandlerMethod)) {
            // 不是 HandlerMethod 类型，可能是静态资源请求，直接放行
            return true;
        }
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        // 获取拦截到的方法
        Method method = handlerMethod.getMethod();
        // 获取方法到的behaviorLimiter注解
        BehaviorLimiter behaviorLimiter = method.getAnnotation(BehaviorLimiter.class);
        if (behaviorLimiter == null) {
            return true;
        }
        // 当前主线程副本中获取登录用户id
        String loginUserId = SessionHelper.getCurrentUserId();
        Assert.isTrue(StringUtils.isNotBlank(loginUserId), "未登录！");
        // 获取请求参数
        ResourceBehaviorRequestVO req = getRequestBody(request);
        Assert.notNull(req, "请求参数");
        // userId:resourceId:behaviorType
        String key = String.format("%s:%s:%s", loginUserId, req.getResourceId(), req.getBehaviorType());
        // 分布式锁简单实现限流，统一登录用户+资源+操作类型在指定时间内只允许操作一次
        boolean lock = redisService.installLockForMS(key, WebConstant.CACHE_NONE, behaviorLimiter.time());
        if (lock) {
            return true;
        }
        throw new BusinessException(behaviorLimiter.message());
    }

    private ResourceBehaviorRequestVO getRequestBody(HttpServletRequest request) {
        try {
            // 获取请求对象
            String bodyJson = HttpHelper.getBodyString(request);
            Assert.isTrue(StringUtils.isNotBlank(bodyJson), "请求参数为空");
            ResourceBehaviorRequestVO req = JsonUtil.fromJson(bodyJson, ResourceBehaviorRequestVO.class);
            Assert.notNull(req.getResourceId(), "资源ID为空");
            Assert.notNull(req.getResourceType(), "资源类型为空");
            Assert.notNull(req.getBehaviorType(), "互动类型为空");
            return req;
        } catch (IOException e) {
            throw new BusinessException("请求参数获取异常");
        }
    }
}